package org.springblade.common.conver;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.common.date.DateUtils;
import org.springblade.common.enums.EnumDesc;
import org.springblade.common.enums.EnumInterface;
import org.springblade.common.enums.EnumUtils;
import org.springblade.common.reflect.ReflectionUtils;

import java.lang.reflect.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.BiFunction;

public class EntityConver {
    private static final Logger logger = LoggerFactory.getLogger(EntityConver.class);

    /**
     * 实体转换类型
     *
     * @author 张浩 2017年4月19日
     */
    public static enum ConverType {
        /** 使用源注解映射 */
        SOURCE,
        /** 使用目标注解映射 */
        TARGET;
    }

    /**
     * 对象转换，默认使用源对象注解
     *
     * @param source
     *            源对象
     * @param targetClass
     *            目标对象类型
     * @return 目标对象
     */
    public static <E> E conver(Object source, Class<E> targetClass) {
        return conver(source, targetClass, ConverType.SOURCE, null);
    }

    /**
     * 对象转换，默认使用源对象注解
     *
     * @param o
     *            源对象
     * @param target
     *            目标对象
     * @return 目标对象
     */
    public static <E> E conver(Object source, E target) {
        return conver(source, target, ConverType.SOURCE, null);
    }

    /**
     * 对象转换，默认使用源对象注解
     *
     * @param source
     *            源对象
     * @param targetClass
     *            目标对象类型
     * @param customConver
     *            转换回调方法，实现部分自定义转换逻辑
     * @return 目标对象
     */
    public static <E> E conver(Object source, Class<E> targetClass, CustomConver customConver) {
        return conver(source, targetClass, ConverType.SOURCE, customConver);
    }

    /**
     * 对象转换
     *
     * @param source
     *            源对象
     * @param targetClass
     *            目标对象类型
     * @param converType
     *            注解生效对象，原对象或目标对象
     * @return 目标对象
     */
    public static <E> E conver(Object source, Class<E> targetClass, ConverType converType) {
        return conver(source, targetClass, converType, null);
    }

    /**
     * 批量对象转换，默认使用源对象注解
     *
     * @param list
     *            源对象集合
     * @param targetClass
     *            目标对象类型
     * @return 目标对象集合
     */
    public static <E> List<E> converList(List<?> list, Class<E> targetClass) {
        return converList(list, targetClass, ConverType.SOURCE, null);
    }

    /**
     * 批量对象转换，默认使用源对象注解
     *
     * @param list
     *            源对象集合
     * @param targetClass
     *            目标对象类型
     * @param converType
     *            注解生效对象，原对象或目标对象
     * @return 目标对象集合
     */
    public static <E> List<E> converList(List<?> list, Class<E> targetClass, ConverType converType) {
        return converList(list, targetClass, converType, null);
    }

    /**
     * 批量对象转换，默认使用源对象注解
     *
     * @param list
     *            源对象集合
     * @param targetClass
     *            目标对象类型
     * @param customConver
     *            转换回调方法，实现部分自定义转换逻辑
     * @return 目标对象集合
     */
    public static <E> List<E> converList(List<?> list, Class<E> targetClass, CustomConver customConver) {
        return converList(list, targetClass, ConverType.SOURCE, customConver);
    }

    /**
     * 批量对象转换，默认使用源对象注解
     *
     * @param list
     *            源对象集合
     * @param targetClass
     *            目标对象类型
     * @param function
     *            转换目标对象额外处理逻辑
     * @return 目标对象集合
     */
    public static <E, T> List<E> converArray(List<T> list, Class<E> targetClass, BiFunction<E, T, E> function) {
        return converArray(list, targetClass, ConverType.SOURCE, function);
    }

    /**
     * 批量对象转换，默认使用源对象注解
     *
     * @param list
     *            源对象集合
     * @param targetClass
     *            目标对象类型
     * @param converType
     *            注解生效对象，原对象或目标对象
     * @param customConver
     *            转换回调方法，实现部分自定义转换逻辑
     * @return 目标对象集合
     */
    public static <E> List<E> converList(List<?> list, Class<E> targetClass, ConverType converType, CustomConver customConver) {
        if (list == null || list.isEmpty())
            return null;
        try {
            List<E> data = new ArrayList<>(list.size());

            Class<?> loopClass = null;
            Class<?> converClass = null;
            Class<?> objectClass = list.get(0).getClass();

            switch (converType) {
            case SOURCE:
                loopClass = objectClass;
                converClass = targetClass;
                break;
            case TARGET:
                loopClass = targetClass;
                converClass = objectClass;
                break;
            }

            List<Field> loopClassFields = new ArrayList<>();
            for (Class<?> clazz = loopClass; clazz != Object.class; clazz = clazz.getSuperclass()) {
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    if (!Modifier.isFinal(field.getModifiers())) {
                        field.setAccessible(true);
                        loopClassFields.add(field);
                    }
                }
            }

            Map<String, Field> converClassFields = new HashMap<>();
            for (Class<?> clazz = converClass; clazz != Object.class; clazz = clazz.getSuperclass()) {
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    if (!Modifier.isFinal(field.getModifiers())) {
                        field.setAccessible(true);
                        converClassFields.put(field.getName(), field);
                    }
                }
            }

            for (Object o : list) {
                E e = conver(o, targetClass, converType, customConver, loopClass, converClass, loopClassFields, converClassFields);
                if (e != null)
                    data.add(e);
            }
            return data;
        } catch (Exception ex) {
            logger.error("Entity converList error, list={}, targetClass={}, converType={}", JSON.toJSONString(list), targetClass, converType, ex);
        }
        return null;
    }

    /**
     * 批量对象转换，默认使用源对象注解
     *
     * @param list
     *            源对象集合
     * @param targetClass
     *            目标对象类型
     * @param converType
     *            注解生效对象，原对象或目标对象
     * @param function
     *            转换目标对象额外处理逻辑
     * @return 目标对象集合
     */
    public static <E, T> List<E> converArray(List<T> list, Class<E> targetClass, ConverType converType, BiFunction<E, T, E> function) {
        if (list == null || list.isEmpty())
            return null;
        try {
            List<E> data = new ArrayList<>(list.size());

            Class<?> loopClass = null;
            Class<?> converClass = null;
            Class<?> objectClass = list.get(0).getClass();

            switch (converType) {
            case SOURCE:
                loopClass = objectClass;
                converClass = targetClass;
                break;
            case TARGET:
                loopClass = targetClass;
                converClass = objectClass;
                break;
            }

            List<Field> loopClassFields = new ArrayList<>();
            for (Class<?> clazz = loopClass; clazz != Object.class; clazz = clazz.getSuperclass()) {
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    if (!Modifier.isFinal(field.getModifiers())) {
                        field.setAccessible(true);
                        loopClassFields.add(field);
                    }
                }
            }

            Map<String, Field> converClassFields = new HashMap<>();
            for (Class<?> clazz = converClass; clazz != Object.class; clazz = clazz.getSuperclass()) {
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    if (!Modifier.isFinal(field.getModifiers())) {
                        field.setAccessible(true);
                        converClassFields.put(field.getName(), field);
                    }
                }
            }

            for (T o : list) {
                E e = conver(o, targetClass, converType, null, loopClass, converClass, loopClassFields, converClassFields);
                if (e != null) {
                    if (function != null) {
                        e = function.apply(e, o);
                    }
                    if (e != null)
                        data.add(e);
                }
            }
            return data;
        } catch (Exception ex) {
            logger.error("Entity converList error, list={}, targetClass={}, converType={}", JSON.toJSONString(list), targetClass, converType, ex);
        }
        return null;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static <E> E conver(Object o, Class<E> targetClass, ConverType converType, CustomConver customConver, Class<?> loopClass, Class<?> converClass,
            List<Field> loopClassFields, Map<String, Field> converClassFields) {
        try {
            E e = targetClass.newInstance();

            for (Field field : loopClassFields) {
                try {
                    Object val = null;
                    Field setField = null;
                    ConverMapper mapper = field.getAnnotation(ConverMapper.class);
                    Precision precision = field.getAnnotation(Precision.class);
                    String targetFielde = null;
                    if (mapper != null) {
                        String converClassName = converClass.getName();
                        if (mapper.targetClass().length == 0) {
                            targetFielde = mapper.targetFielde()[0];
                        } else {
                            for (int i = 0; i < mapper.targetClass().length; i++) {
                                String mapperClass = mapper.targetClass()[i];

                                if (mapperClass.equals(converClassName)) {
                                    targetFielde = mapper.targetFielde()[i];
                                    break;
                                }
                            }
                        }
                    }

                    String fieldName = null;
                    if (targetFielde != null && !targetFielde.isEmpty()) {
                        fieldName = targetFielde;
                    } else {
                        fieldName = field.getName();
                    }

                    if (converType == ConverType.SOURCE) {
                        val = field.get(o);
                        setField = converClassFields.get(fieldName);
                    } else if (converType == ConverType.TARGET) {
                        Field getField = converClassFields.get(fieldName);

                        if (getField != null) {
                            val = getField.get(o);
                        }

                        setField = field;
                    }

                    enumDescConver(o, e, field);

                    if (setField == null)
                        continue;

                    if (customConver != null)
                        val = customConver.handler(val, setField);

                    if (val == null) {
                        DefaultVal defaultVal = field.getAnnotation(DefaultVal.class);
                        if (defaultVal != null)
                            val = defaultVal.val();
                        else
                            continue;
                    } else if (precision != null) {
                        int movePoint = precision.movePoint();
                        int scale = precision.scale();
                        RoundingMode roundingMode = precision.roundingMode();

                        BigDecimal bigDecimal = new BigDecimal(val.toString());
                        bigDecimal = bigDecimal.movePointRight(movePoint).setScale(scale, roundingMode);

                        if (setField.getType().equals(Short.class)) {
                            val = bigDecimal.shortValue();
                        } else if (setField.getType().equals(Integer.class)) {
                            val = bigDecimal.intValue();
                        } else if (setField.getType().equals(Long.class)) {
                            val = bigDecimal.longValue();
                        } else if (setField.getType().equals(Float.class)) {
                            val = bigDecimal.floatValue();
                        } else if (setField.getType().equals(Double.class)) {
                            val = bigDecimal.doubleValue();
                        } else if (setField.getType().equals(String.class)) {
                            val = bigDecimal.toString();
                        } else {
                            val = bigDecimal;
                        }
                    }

                    // 类型转换
                    if (Collection.class.isAssignableFrom(setField.getType())) {// 集合转换
                        Type genericType = ((ParameterizedType) setField.getGenericType()).getActualTypeArguments()[0];
                        if (genericType instanceof WildcardType) {
                            WildcardType wildcardType = (WildcardType) genericType;
                            Type[] bounds = wildcardType.getLowerBounds();
                            if (bounds.length == 0) {
                                bounds = wildcardType.getUpperBounds();
                            }
                            genericType = bounds[0];
                        }
                        Class setFieldGenericClass = (Class) genericType;
                        if (Collection.class.isAssignableFrom(val.getClass())) {
                            Collection values = ((Collection) val);
                            Collection setFieldCollection = null;

                            if (Set.class.isAssignableFrom(setField.getType()))
                                setFieldCollection = new HashSet<>();
                            else if (List.class.isAssignableFrom(setField.getType()))
                                setFieldCollection = new ArrayList<>();

                            for (Object obj : values) {
                                if (obj == null)
                                    continue;
                                if (setFieldGenericClass.equals(String.class)) {
                                    obj = obj.toString();
                                } else if (setFieldGenericClass.equals(Short.class)) {
                                    obj = Short.parseShort(obj.toString());
                                } else if (setFieldGenericClass.equals(Integer.class)) {
                                    obj = Integer.parseInt(obj.toString());
                                } else if (setFieldGenericClass.equals(Long.class)) {
                                    obj = Long.parseLong(obj.toString());
                                } else if (setFieldGenericClass.equals(Float.class)) {
                                    obj = Float.parseFloat(obj.toString());
                                } else if (setFieldGenericClass.equals(Double.class)) {
                                    obj = Double.parseDouble(obj.toString());
                                } else if (setFieldGenericClass.isEnum()) {
                                    if (obj.getClass().equals(String.class)) {
                                        obj = Enum.valueOf(setFieldGenericClass, obj.toString());
                                    }
                                } else if (!setFieldGenericClass.equals(obj.getClass())) {// 复合对象转换
                                    obj = conver(obj, setFieldGenericClass, converType);
                                }
                                setFieldCollection.add(obj);
                            }
                            if (!setFieldCollection.isEmpty())
                                val = setFieldCollection;
                        } else if (val.getClass().equals(String.class)) {
                            val = JSON.parseArray(val.toString(), setFieldGenericClass);
                        }
                    } else if (Map.class.isAssignableFrom(setField.getType()) && Map.class.isAssignableFrom(val.getClass())) {
                        // 不处理
                    } else if (!setField.getType().equals(val.getClass())) {
                        if (setField.getType().equals(Date.class)) {// 日期转换
                            if (val.getClass().equals(Long.class))
                                val = new Date((Long) val);
                            else if (val.getClass().equals(String.class))
                                val = DateUtils.convertDateString(val.toString());
                        } else if (setField.getType().equals(Long.class)) {
                            if (val.getClass().equals(Date.class))// 日期转换
                                val = ((Date) val).getTime();
                            else if (val.getClass().equals(String.class)) {
                                if (DateUtils.validateLongDateFormat(val.toString()) || DateUtils.validateUnsignedDateFormat(val.toString())
                                        || DateUtils.validateShortDateFormat(val.toString()))// 日期转换
                                    val = DateUtils.convertDateStringToMillisecond(val.toString());
                                else
                                    val = Long.parseLong(val.toString());
                            } else if (val.getClass().equals(Integer.class)) {
                                val = ((Integer) val).longValue();
                            }
                        } else if (setField.getType().equals(String.class)) {
                            if (val.getClass().equals(Date.class))// 日期转换
                                val = DateUtils.convertToLongDateString((Date) val);
                            else if (!val.getClass().isPrimitive())
                                val = JSON.toJSONString(val);
                            else
                                val = val.toString();
                        } else if (setField.getType().equals(Integer.class)) {
                            if (val.getClass().equals(String.class)) {
                                val = Integer.parseInt(val.toString());
                            } else if (val.getClass().equals(Long.class)) {
                                val = ((Long) val).intValue();
                            } else if (val.getClass().equals(Byte.class)) {
                                val = ((Byte) val).intValue();
                            }

                        } else if (setField.getType().equals(Double.class)) {
                            if (val.getClass().equals(String.class)) {
                                val = Double.parseDouble(val.toString());
                            }
                        } else if (setField.getType().equals(Boolean.class)) {
                            if (val.getClass().equals(String.class)) {
                                val = Boolean.parseBoolean(val.toString());
                            }
                        } else if (setField.getType().equals(Float.class)) {
                            if (val.getClass().equals(String.class)) {
                                val = Float.parseFloat(val.toString());
                            }
                        } else if (setField.getType().equals(Short.class)) {
                            if (val.getClass().equals(String.class)) {
                                val = Short.parseShort(val.toString());
                            }
                        } else if (setField.getType().equals(Byte.class)) {
                            if (val.getClass().equals(String.class)) {
                                val = Byte.parseByte(val.toString());
                            } else if (val.getClass().equals(Integer.class)) {
                                val = ((Integer) val).byteValue();
                            }
                        } else if (setField.getType().isEnum()) {
                            if (val.getClass().equals(String.class)) {
                                val = Enum.valueOf((Class) setField.getType(), val.toString());
                            }
                        } else if (setField.getType().equals(BigDecimal.class)) {
                            val = new BigDecimal(val.toString());
                        } else if (setField.getType().equals(StringBuilder.class)) {
                            val = new StringBuilder(val.toString());
                        } else if (!setField.getType().isPrimitive()) {// 复合对象转换
                            if (val.getClass().equals(String.class))
                                val = JSON.parseObject(val.toString(), setField.getType());
                            else
                                val = conver(val, setField.getType(), converType);
                        }
                    }

                    setField.set(e, val);

                } catch (Exception ex) {
                    logger.error("Entity conver error, object={}, targetClass={}, converType={}, loopClass={}", o, targetClass, converType, loopClass, ex);
                }
            }

            return e;
        } catch (Exception ex) {
            logger.error("Entity conver error, object={}, targetClass={}, converType={}", o, targetClass, converType, ex);
        }
        return null;
    }

    /**
     * 对象转换，默认使用源对象注解
     *
     * @param source
     *            源对象
     * @param targetClass
     *            目标对象类型
     * @param converType
     *            注解生效对象，原对象或目标对象
     * @param customConver
     *            转换回调方法，实现部分自定义转换逻辑
     * @return 目标对象
     */
    public static <E> E conver(Object source, Class<E> targetClass, ConverType converType, CustomConver customConver) {
        if (targetClass == null)
            return null;

        try {
            E target = targetClass.newInstance();
            return conver(source, target, converType, customConver);
        } catch (Exception e) {
            logger.error("Entity conver error, source={}, targetClass={}, converType={}", JSON.toJSONString(source), targetClass, converType, e);
        }

        return null;
    }

    /**
     * 对象转换，默认使用源对象注解
     *
     * @param source
     *            源对象
     * @param target
     *            目标对象
     * @param converType
     *            注解生效对象，原对象或目标对象
     * @param customConver
     *            转换回调方法，实现部分自定义转换逻辑
     * @return 目标对象
     */
    public static <E> E conver(Object source, E target, ConverType converType, CustomConver customConver) {
        if (source == null || target == null || converType == null) {
            return null;
        }
        try {
            Class<?> loopClass = null;
            Class<?> converClass = null;
            Class<?> objectClass = source.getClass();
            Class<?> targetClass = target.getClass();

            switch (converType) {
            case SOURCE:
                loopClass = objectClass;
                converClass = targetClass;
                break;
            case TARGET:
                loopClass = targetClass;
                converClass = objectClass;
                break;
            }

            for (Class<?> clazz = loopClass; clazz != Object.class; clazz = clazz.getSuperclass()) {
                try {
                    Field[] fields = clazz.getDeclaredFields();

                    if (fields == null)
                        continue;

                    for (Field field : fields) {
                        if (Modifier.isFinal(field.getModifiers()))
                            continue;

                        field.setAccessible(true);

                        Object val = null;
                        Field setField = null;
                        ConverMapper mapper = field.getAnnotation(ConverMapper.class);
                        Precision precision = field.getAnnotation(Precision.class);
                        String targetFielde = null;
                        if (mapper != null) {
                            String converClassName = converClass.getName();
                            if (mapper.targetClass().length == 0) {
                                targetFielde = mapper.targetFielde()[0];
                            } else {
                                for (int i = 0; i < mapper.targetClass().length; i++) {
                                    String mapperClass = mapper.targetClass()[i];

                                    if (mapperClass.equals(converClassName)) {
                                        targetFielde = mapper.targetFielde()[i];
                                        break;
                                    }
                                }
                            }
                        }

                        String fieldName = null;
                        if (targetFielde != null && !targetFielde.isEmpty()) {
                            fieldName = targetFielde;
                        } else {
                            fieldName = field.getName();
                        }

                        if (converType == ConverType.SOURCE) {
                            val = field.get(source);

                            setField = ReflectionUtils.getDeclaredField(converClass, fieldName);

                            if (setField != null)
                                setField.setAccessible(true);
                        } else if (converType == ConverType.TARGET) {

                            Field getField = ReflectionUtils.getDeclaredField(converClass, fieldName);

                            if (getField != null) {
                                getField.setAccessible(true);
                                val = getField.get(source);
                            }

                            setField = field;
                        }

                        enumDescConver(source, target, field);

                        if (setField == null)
                            continue;

                        if (customConver != null)
                            val = customConver.handler(val, setField);

                        if (val == null) {
                            DefaultVal defaultVal = field.getAnnotation(DefaultVal.class);
                            if (defaultVal != null)
                                val = defaultVal.val();
                            else
                                continue;
                        } else if (precision != null) {
                            int movePoint = precision.movePoint();
                            int scale = precision.scale();
                            RoundingMode roundingMode = precision.roundingMode();

                            BigDecimal bigDecimal = new BigDecimal(val.toString());
                            bigDecimal = bigDecimal.movePointRight(movePoint).setScale(scale, roundingMode);

                            if (setField.getType().equals(Short.class)) {
                                val = bigDecimal.shortValue();
                            } else if (setField.getType().equals(Integer.class)) {
                                val = bigDecimal.intValue();
                            } else if (setField.getType().equals(Long.class)) {
                                val = bigDecimal.longValue();
                            } else if (setField.getType().equals(Float.class)) {
                                val = bigDecimal.floatValue();
                            } else if (setField.getType().equals(Double.class)) {
                                val = bigDecimal.doubleValue();
                            } else if (setField.getType().equals(String.class)) {
                                val = bigDecimal.toString();
                            } else {
                                val = bigDecimal;
                            }
                        }

                        // 类型转换
                        if (Collection.class.isAssignableFrom(setField.getType())) {// 集合转换
                            Type genericType = ((ParameterizedType) setField.getGenericType()).getActualTypeArguments()[0];
                            if (genericType instanceof WildcardType) {
                                WildcardType wildcardType = (WildcardType) genericType;
                                Type[] bounds = wildcardType.getLowerBounds();
                                if (bounds.length == 0) {
                                    bounds = wildcardType.getUpperBounds();
                                }
                                genericType = bounds[0];
                            }
                            Class setFieldGenericClass = (Class) genericType;
                            if (Collection.class.isAssignableFrom(val.getClass())) {
                                Collection values = ((Collection) val);
                                Collection setFieldCollection = null;

                                if (Set.class.isAssignableFrom(setField.getType()))
                                    setFieldCollection = new HashSet<>();
                                else if (List.class.isAssignableFrom(setField.getType()))
                                    setFieldCollection = new ArrayList<>();

                                for (Object obj : values) {
                                    if (obj == null)
                                        continue;
                                    if (setFieldGenericClass.equals(String.class)) {
                                        obj = obj.toString();
                                    } else if (setFieldGenericClass.equals(Short.class)) {
                                        obj = Short.parseShort(obj.toString());
                                    } else if (setFieldGenericClass.equals(Integer.class)) {
                                        obj = Integer.parseInt(obj.toString());
                                    } else if (setFieldGenericClass.equals(Long.class)) {
                                        obj = Long.parseLong(obj.toString());
                                    } else if (setFieldGenericClass.equals(Float.class)) {
                                        obj = Float.parseFloat(obj.toString());
                                    } else if (setFieldGenericClass.equals(Double.class)) {
                                        obj = Double.parseDouble(obj.toString());
                                    } else if (setFieldGenericClass.isEnum()) {
                                        if (obj.getClass().equals(String.class)) {
                                            obj = Enum.valueOf(setFieldGenericClass, obj.toString());
                                        }
                                    } else if (!setFieldGenericClass.equals(obj.getClass())) {// 复合对象转换
                                        obj = conver(obj, setFieldGenericClass, converType);
                                    }
                                    setFieldCollection.add(obj);
                                }
                                if (!setFieldCollection.isEmpty())
                                    val = setFieldCollection;
                            } else if (val.getClass().equals(String.class)) {
                                val = JSON.parseArray(val.toString(), setFieldGenericClass);
                            }
                        } else if (Map.class.isAssignableFrom(setField.getType()) && Map.class.isAssignableFrom(val.getClass())) {
                            // 不处理
                        } else if (!setField.getType().equals(val.getClass())) {
                            if (setField.getType().equals(Date.class)) {// 日期转换
                                if (val.getClass().equals(Long.class))
                                    val = new Date((Long) val);
                                else if (val.getClass().equals(String.class))
                                    val = DateUtils.convertDateString(val.toString());
                            } else if (setField.getType().equals(Long.class)) {
                                if (val.getClass().equals(Date.class))// 日期转换
                                    val = ((Date) val).getTime();
                                else if (val.getClass().equals(String.class)) {
                                    if (DateUtils.validateLongDateFormat(val.toString()) || DateUtils.validateUnsignedDateFormat(val.toString())
                                            || DateUtils.validateShortDateFormat(val.toString()))// 日期转换
                                        val = DateUtils.convertDateStringToMillisecond(val.toString());
                                    else
                                        val = Long.parseLong(val.toString());
                                } else if (val.getClass().equals(Integer.class)) {
                                    val = ((Integer) val).longValue();
                                }
                            } else if (setField.getType().equals(String.class)) {
                                if (val.getClass().equals(Date.class))// 日期转换
                                    val = DateUtils.convertToLongDateString((Date) val);
                                else if (!val.getClass().isPrimitive())
                                    val = JSON.toJSONString(val);
                                else
                                    val = val.toString();
                            } else if (setField.getType().equals(Integer.class)) {
                                if (val.getClass().equals(String.class)) {
                                    val = Integer.parseInt(val.toString());
                                } else if (val.getClass().equals(Long.class)) {
                                    val = ((Long) val).intValue();
                                } else if (val.getClass().equals(Byte.class)) {
                                    val = ((Byte) val).intValue();
                                }

                            } else if (setField.getType().equals(Double.class)) {
                                if (val.getClass().equals(String.class)) {
                                    val = Double.parseDouble(val.toString());
                                }
                            } else if (setField.getType().equals(Boolean.class)) {
                                if (val.getClass().equals(String.class)) {
                                    val = Boolean.parseBoolean(val.toString());
                                }
                            } else if (setField.getType().equals(Float.class)) {
                                if (val.getClass().equals(String.class)) {
                                    val = Float.parseFloat(val.toString());
                                }
                            } else if (setField.getType().equals(Short.class)) {
                                if (val.getClass().equals(String.class)) {
                                    val = Short.parseShort(val.toString());
                                }
                            } else if (setField.getType().equals(Byte.class)) {
                                if (val.getClass().equals(String.class)) {
                                    val = Byte.parseByte(val.toString());
                                } else if (val.getClass().equals(Integer.class)) {
                                    val = ((Integer) val).byteValue();
                                }
                            } else if (setField.getType().isEnum()) {
                                if (val.getClass().equals(String.class)) {
                                    val = Enum.valueOf((Class) setField.getType(), val.toString());
                                }
                            } else if (setField.getType().equals(BigDecimal.class)) {
                                val = new BigDecimal(val.toString());
                            } else if (!setField.getType().isPrimitive()) {// 复合对象转换
                                if (val.getClass().equals(String.class))
                                    val = JSON.parseObject(val.toString(), setField.getType());
                                else
                                    val = conver(val, setField.getType(), converType);
                            }
                        }

                        setField.set(target, val);

                    }
                } catch (Exception ex) {
                    logger.error("Entity conver error, source={}, target={}, converType={}, loopClass={}", JSON.toJSONString(source), JSON.toJSONString(target), converType,
                            loopClass, ex);
                }
            }

            return target;
        } catch (Exception ex) {
            logger.error("Entity conver error, source={}, target={}, converType={}", JSON.toJSONString(source), JSON.toJSONString(target), converType, ex);
        }
        return null;
    }

    /**
     * 枚举描述字段转换
     */
    private static void enumDescConver(Object source, Object target, Field field) {
        // 枚举描述字段转换
        String descFielde = null;
        Class<? extends EnumInterface> enumClass = null;
        try {
            EnumDesc enumDesc = field.getAnnotation(EnumDesc.class);
            if (enumDesc == null)
                return;

            descFielde = enumDesc.descFielde();
            if (descFielde == null || descFielde.isEmpty())
                descFielde = field.getName() + "Desc";

            enumClass = enumDesc.enumClass();

            Field setField = ReflectionUtils.getDeclaredField(target.getClass(), descFielde);

            if (setField == null)
                return;

            Object enumVal = field.get(source);
            if (enumVal == null)
                return;

            String desc = EnumUtils.getByCode(enumClass, (Integer) enumVal).getDesc();

            setField.setAccessible(true);
            setField.set(target, desc);
        } catch (Exception e) {
            logger.error("枚举描述字段转换失败, source={}, target={}, field={}, descFielde={}, enumClass={}", source, target, field, descFielde, enumClass, e);
        }
    }

    /**
     * 自定义类型转换接口
     *
     * @author 张浩 2017年5月15日
     */
    public interface CustomConver {
        public Object handler(Object val, Field setField);
    }

}
